# -*- coding: utf-8 -*-

import argparse, os, inspect, datetime, platform
import random
from subprocess import run

# 定义全局函数字典(勿删)
functions = {}
# 定义是否使用预设菜单布局, True为使用, False为不使用
USE_PRESET_MENU_IT = False
# 定义缓存文件路径
kylin_file_path = "/tmp/kylin_install_file/"


# 装饰器定义，接受两个参数：key 和 description
def switch_func(key, description, hidden=False):
    """
    装饰器函数，用于将函数注册到全局的函数映射表中

    Args:
        key (str): 菜单项的键名。
        description (str): 菜单项的描述信息。
        hidden (bool, optional): 是否隐藏该菜单项。默认为False

    Returns:
        function: 装饰器函数，用于将函数注册到全局的函数映射表中
    """

    def decorator(func):
        func.menu_key = key
        func.menu_description = description
        if hidden:
            func.hidden = True
        else:
            func.hidden = False
        functions[key] = func
        return func

    return decorator


# 公有执行函数封装
class Kylin_Tools_Common:
    # 执行封装
    def cmd(self, command: str):
        """
        执行语句命令
        :param command: 需要执行的命令
        :return: 返回执行结果
        """
        back = run(command, shell=True, capture_output=True, text=True)
        if back.returncode == 0:
            return back.stdout

    def soft_down_file(self, file_urls, file_path):
        """
        下载软件安装文件并安装
        :param file_urls: 需要下载的文件URL
        :param file_path: 下载文件存放路径
        :return: 无返回值
        """
        # 本地如果没有下载文件夹就新建
        if not os.path.exists(file_path):
            os.system("mkdir -p {}".format(file_path))
        for down_name, down_url in file_urls.items():
            # 查看本地有没有缓存文件，如果有就安装，没有就下载安装
            file_name = os.path.basename(down_url)
            if os.path.exists(os.path.join(file_path, file_name)):
                # 本地有缓存，使用缓存安装
                print("本地有缓存，使用缓存安装:{}".format(down_name))
            else:
                # 正在下载并安装
                print("正在下载并安装:{}".format(down_name))
                os.system(
                    "sudo wget -P {} {} -q --show-progress".format(file_path, down_url)
                )

            try:
                # 正在安装
                print("正在安装{}...".format(down_name))
                self.cmd("sudo dpkg -i {}/{}".format(file_path, file_name))
            except:
                # 安装失败
                print("安装{}失败!!!".format(down_name))
                return False
            else:
                # 安装完成
                print("安装{}完成!!!".format(down_name))
                return True


# 文本类封装
class Kylin_Script_Print:
    def __init__(self) -> None:
        self.logo = inspect.cleandoc(
            r"""
             ____  ____        __   __                ________  ____      ____ 
            |_   ||   _|      [  | [  |              |_   __  ||_  _|    |_  _|
              | |__| |  .---.  | |  | |  .--.          | |_ \_|  \ \  /\  / /  
              |  __  | / /__\\ | |  | |/ .'`\ \        |  _|      \ \/  \/ /   
             _| |  | |_| \__., | |  | || \__. |  _    _| |_        \  /\  /    
            |____||____|'.__.'[___][___]'.__.'  )_/  |_____|        \/  \/     

            ---欢迎使用FW工具箱, 让我们一起来当个废物吧(手动划掉)---
        """
        )

        # 当前运行环境
        self.script_env = inspect.cleandoc(
            f"""
            ---当前系统时间: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
            ---当前操作系统: {kylin_tools_common.cmd('cat /etc/os-release | grep ^ID | sed "s/ID=//" | sed -n 1p').strip() if platform.system() == "Linux" else "Windows"}
            ---当前系统架构: {platform.machine()}
            ---当前工作目录: {os.getcwd()}
            ---当前用户名: {os.getlogin()}
        """
        )

        # 预设菜单
        self.script_much = inspect.cleandoc(
            r"""
            0 退出脚本          0.0 显示菜单
            ====================

            ====================
            脚本更新时间: 2024.2.1
            如有问题请联系开发者: Warren
        """
        )

        # 预设菜单(内部功能)
        self.script_much_it = inspect.cleandoc(
            """
            ————————————内部功能（慎用）————————————
            暂无内部功能
        """
        )
        self.script_much_all = (
            self.logo + "\n" + self.script_env + "\n" + self.script_much
        )

    # 显示菜单函数，根据show_hidden参数决定是否显示隐藏功能
    def show_menu(self, show_hidden: bool = False):
        """
        显示菜单函数, 根据show_hidden参数决定是否显示隐藏功能
        :param show_hidden: 是否显示隐藏功能
        :return: 无返回值
        """
        if USE_PRESET_MENU_IT:
            print(Kylin_Script_Print().script_much_all)
        else:
            print(Kylin_Script_Print().logo)
            menu_items = [
                f"{func.menu_key} {func.menu_description}"
                for func in functions.values()
                # show_hidden为True时显示所有菜单项，否则只显示非隐藏项
                # func.hidden为False时只显示非隐藏项
                if show_hidden or not func.hidden
            ]
            for i in range(0, len(menu_items)):
                print(" | ".join(menu_items[i : i + 1]))


#
class Kylin_Tools_Script:
    @switch_func("0", "退出脚本")
    def function1(self):
        print("执行退出脚本")
        exit()

    @switch_func("0.0", "显示菜单")
    def function2(self):
        print("显示菜单")
        kylin_script_print.show_menu(args.show_hidden)

    @switch_func("1.1", "Apt-换源")
    # Apt换源
    def apt_mirror(self):
        # 执行换源脚本
        kylin_tools_common.cmd("sudo bash <(curl -sSL https://linuxmirrors.cn/main.sh)")

    @switch_func("1.2", "pip-换源")
    def pip_mirror(self):
        mirror = int(
            input(
                "请选择镜像源：(输入序号选择)\n1 清华源\n2 中科大源\n3 豆瓣源\n4 阿里源\n>>> "
            )
        )
        if mirror == 1:
            kylin_tools_common.cmd(
                "pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple"
            )
        elif mirror == 2:
            kylin_tools_common.cmd(
                "pip3 config set global.index-url https://pypi.mirrors.ustc.edu.cn/simple/"
            )
        elif mirror == 3:
            kylin_tools_common.cmd(
                "pip3 config set global.index-url https://pypi.douban.com/simple/"
            )
        elif mirror == 4:
            kylin_tools_common.cmd(
                "pip3 config set global.index-url http://mirrors.aliyun.com/pypi/simple/"
            )
        else:
            print("输入错误，请重新输入！")

    @switch_func("1.3", "K3S安装配置")
    def k3s_install(self):
        # 安装k3s
        kylin_tools_common.cmd(
            "curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -"
        )
        # 查看token
        kylin_tools_common.cmd("sudo cat /var/lib/rancher/k3s/server/node-token")
        # 查看节点
        kylin_tools_common.cmd("sudo kubectl get node")
        # 查看服务
        kylin_tools_common.cmd("sudo kubectl get svc")
        # 查看pod
        kylin_tools_common.cmd("sudo kubectl get pod")
        # 配置K3S环境变量
        kylin_tools_common.cmd(
            "echo 'export KUBECONFIG=/etc/rancher/k3s/k3s.yaml' >> ~/.bashrc"
        )
        # 配置K3S补全
        kylin_tools_common.cmd("sudo k3s kubectl completion bash >> ~/.bashrc")

    @switch_func("1.4", "Helm安装配置")
    def helm_install(self):
        # 安装Helm, 使用二进制安装
        kylin_tools_common.cmd(
            "curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3"
        )
        kylin_tools_common.cmd("chmod 700 get_helm.sh")
        kylin_tools_common.cmd("sudo ./get_helm.sh")
        # 查看版本
        kylin_tools_common.cmd("helm version")
        # 添加Helm仓库
        kylin_tools_common.cmd("helm repo add stable https://charts.helm.sh/stable")
        kylin_tools_common.cmd(
            "helm repo add bitnami https://charts.bitnami.com/bitnami"
        )
        # 更新Helm仓库
        kylin_tools_common.cmd("helm repo update")
        # Helm补全
        kylin_tools_common.cmd("sudo helm completion bash >> ~/.bashrc")
    
    @switch_func("1.5", "Github520-Hosts")
    def github520_hosts(self):
        # 下载Github520-Hosts
        kylin_tools_common.cmd("wget -qO - https://raw.hellogithub.com/hosts | cat - >> /etc/hosts")
        # 查看是否生效
        kylin_tools_common.cmd("ping github.com")

    @switch_func("1.6", "K3S换源")
    def k3s_mirror(self):
        # K3S换源
        kylin_tools_common.cmd(
            "sudo curl -sfL https://get.k3s.io | INSTALL_K3S_MIRROR=cn sh -"
        )
    
    @switch_func("1.7", "Docker换源")
    def docker_mirror(self):
        # Docker换源
        kylin_tools_common.cmd(
            "sudo curl -fsSL https://get.docker.com | bash -s -- --mirror Aliyun"
        )

# 创建命令行解析器
parser = argparse.ArgumentParser(description="Kylin System Script")
parser.add_argument(
    "-f", "--function", help="指定要执行的功能", choices=list(functions.keys())
)
parser.add_argument("-k", "--show-hidden", action="store_true", help="显示隐藏菜单项")

# 解析命令行参数
args = parser.parse_args()

# 实例化
kylin_tools_common = Kylin_Tools_Common()
kylin_script_print = Kylin_Script_Print()


def main():
    # 命令行参数执行
    if args.function:
        functions[args.function]()
    else:
        # 显示预设菜单
        kylin_script_print.show_menu(args.show_hidden)
        while True:
            # 获取用户输入
            choice = input("如需执行脚本功能, 请输入菜单选项==>")

            # 根据用户输入执行对应的函数
            if choice in functions:
                functions[choice](Kylin_Tools_Script())
            else:
                print("输入错误，请重新输入！")


if __name__ == "__main__":
    main()
